package com.zeyu.framework.modules.common.openid.provider;

import com.zeyu.framework.core.common.mapper.JsonMapper;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.List;

/**
 * WeiXin第三方登录服务提供者
 * Created by zeyuphoenix on 2017/1/5.
 */
public class WeiXinAuthProvider {

    // ================================================================
    // Constants
    // ================================================================

    /**
     * uid
     */
    private static final long serialVersionUID = 1L;
    /**
     * logger
     */
    private static final Logger logger = LoggerFactory.getLogger(WeiXinAuthProvider.class);

    // auth url
    private static final String PROFILE_URL = "https://api.weixin.qq.com/sns/userinfo";
    private static final String OAUTH_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";

    // set this to the list of extended permissions you want
    private static final String AuthenticateOnlyPerms = "snsapi_userinfo";

    // ================================================================
    // Fields
    // ================================================================

    // ================================================================
    // Constructors
    // ================================================================

    /**
     * Stores configuration for the provider
     * @throws Exception
     */
    public WeiXinAuthProvider() throws Exception {
    }

    // ================================================================
    // Methods from/for super Interfaces or SuperClass
    // ================================================================

    // ================================================================
    // Public or Protected Methods
    // ================================================================

    public String auth(String code, String appid, String secret) {
        logger.info("auth code is:" + code);
        StringBuilder url = new StringBuilder(OAUTH_ACCESS_TOKEN_URL);
        url.append("?appid=").append(appid).append("&");
        url.append("secret=").append(secret).append("&");
        url.append("code=").append(code).append("&");
        url.append("grant_type=").append("authorization_code");
        String result = null;
        CloseableHttpClient hc = HttpClientBuilder.create().build();
        try {
            HttpGet http_get = new HttpGet(url.toString());
            HttpEntity entity = hc.execute(http_get).getEntity();
            result = IOUtils.toString(entity.getContent(), "UTF-8");
            http_get.clone();
        } catch (Exception e) {
            logger.error("auth error: ", e);
        } finally {
            try {
                hc.close();
            } catch (Exception ignored) {
            }
        }

        logger.info("access token return is : {}", result);
        if (result != null) {
            JSONObject accessInfo = new JSONObject(result);
            if (accessInfo.optString("errcode") == null) {
                UserInfo userInfo = getUserInfo(accessInfo.optString("access_token"), accessInfo.optString("openid"));

                logger.info("get user info return is : {}", userInfo);

                return userInfo.getUnionid();
            }
        }

        return null;
    }

    public UserInfo getUserInfo(String access_token, String openid) {
        StringBuilder url = new StringBuilder(PROFILE_URL);
        url.append("?access_token=").append(access_token).append("&");
        url.append("openid=").append(openid).append("&");
        url.append("lang=zh_CN");
        logger.debug("get user info :" + url);

        String result = null;
        CloseableHttpClient hc = HttpClientBuilder.create().build();
        try {
            HttpGet http_get = new HttpGet(url.toString());
            HttpEntity entity = hc.execute(http_get).getEntity();
            result = IOUtils.toString(entity.getContent(), "UTF-8");
            http_get.clone();
        } catch (Exception e) {
            logger.error("get user info error: ", e);
        } finally {
            try {
                hc.close();
            } catch (Exception ignored) {
            }
        }

        logger.info("get user info return is : {}", result);
        if (result != null) {
            return JsonMapper.getInstance().fromJson(result, UserInfo.class);
        }

        return null;
    }

    // ================================================================
    // Getter & Setter
    // ================================================================

    // ================================================================
    // Private Methods
    // ================================================================

    /**
     * 用户信息
     */
    private static class UserInfo implements Serializable {

        // ================================================================
        // Fields
        // ================================================================

        private String language;
        private String openid;
        private String nickname;
        private String sex;
        private String province;
        private String city;
        private String country;
        private String headimgurl;
        private List<String> privilege;
        private String unionid;

        // ================================================================
        // Constructors
        // ================================================================

        // ================================================================
        // Methods from/for super Interfaces or SuperClass
        // ================================================================

        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this);
        }

        // ================================================================
        // Getter & Setter
        // ================================================================

        public String getOpenid() {
            return openid;
        }

        public void setOpenid(String openid) {
            this.openid = openid;
        }

        public String getSex() {
            return sex;
        }

        public void setSex(String sex) {
            this.sex = sex;
        }

        public String getProvince() {
            return province;
        }

        public void setProvince(String province) {
            this.province = province;
        }

        public String getCity() {
            return city;
        }

        public void setCity(String city) {
            this.city = city;
        }

        public String getCountry() {
            return country;
        }

        public void setCountry(String country) {
            this.country = country;
        }

        public String getHeadimgurl() {
            return headimgurl;
        }

        public void setHeadimgurl(String headimgurl) {
            this.headimgurl = headimgurl;
        }

        public List<String> getPrivilege() {
            return privilege;
        }

        public void setPrivilege(List<String> privilege) {
            this.privilege = privilege;
        }

        public String getUnionid() {
            return unionid;
        }

        public void setUnionid(String unionid) {
            this.unionid = unionid;
        }

        public String getNickname() {
            return nickname;
        }

        public void setNickname(String nickname) {
            this.nickname = nickname;
        }

        public String getLanguage() {
            return language;
        }

        public void setLanguage(String language) {
            this.language = language;
        }
    }

}
